﻿// (c) Norbert Huffschmid
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using SpinDotters.Core;

namespace SpinDotters.Widgets
{
    /// <summary>
    /// Stopwatch control
    /// </summary>
    [TemplatePart(Name = "PART_ResetButton", Type = typeof(Button))]
    [TemplatePart(Name = "PART_StartStopButton", Type = typeof(Button))]
    public partial class StopWatch : SpinningControlContainer, INotifyPropertyChanged
    {
        /// <summary>
        /// Notifies listeners that a property value has changed.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;


        private DispatcherTimer timer = new DispatcherTimer();
        private int counter;
        private Button startStopButton;
        private Button resetButton;

        
        /// <summary>
        /// Default constructor
        /// </summary>
        public StopWatch()
        {
            this.DefaultStyleKey = typeof(StopWatch);

            this.counter = 0;

            timer.Interval = new TimeSpan(0, 0, 1);
            timer.Tick += new EventHandler(timer_Tick);

            this.Unloaded += new RoutedEventHandler(StopWatch_Unloaded);

            this.DataContext = this;
        }

        /// <summary>
        /// Starts the stopwatch
        /// </summary>
        public void Start()
        {
            this.timer.Start();

            OnPropertyChanged("IsRunning");
        }

        /// <summary>
        /// Stops the stopwatch
        /// </summary>
        public void Stop()
        {
            this.timer.Stop();

            OnPropertyChanged("IsRunning");
        }

        /// <summary>
        /// Reset the stopwatch
        /// </summary>
        public void Reset()
        {
            this.counter = 0;
            ShowTime();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.startStopButton = this.GetTemplateChild("PART_StartStopButton") as Button;
            this.resetButton = this.GetTemplateChild("PART_ResetButton") as Button;

            if (this.startStopButton != null)
            {
                this.startStopButton.Click += new RoutedEventHandler(startStopButton_Click);
                this.startStopButton.SizeChanged +=new SizeChangedEventHandler(Button_SizeChanged);
            }

            if (this.resetButton != null)
            {
                this.resetButton.Click += new RoutedEventHandler(resetButton_Click);
                this.resetButton.SizeChanged += new SizeChangedEventHandler(Button_SizeChanged);
            }
        }


        protected virtual void OnPropertyChanged(String info)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(info));
        }


        private void Button_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            // TODO: find XAML solution for this!

            Button button = sender as Button;

            if (button != null)
            {
                // make button square-sized
                if (button.ActualWidth < button.ActualHeight)
                    button.Width = button.ActualHeight;
            }
        }

        private void startStopButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.timer.IsEnabled) // means running ...
            {
                this.Stop();
            }
            else
            {
                this.Start();
            }
        }

        private void resetButton_Click(object sender, RoutedEventArgs e)
        {
            this.Reset();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            this.counter++;
            ShowTime();
        }

        private void StopWatch_Unloaded(object sender, RoutedEventArgs e)
        {
            Stop();
        }

        private void ShowTime()
        {
            OnPropertyChanged("HoursHigh");
            OnPropertyChanged("HoursLow");
            OnPropertyChanged("MinutesHigh");
            OnPropertyChanged("MinutesLow");
            OnPropertyChanged("SecondsHigh");
            OnPropertyChanged("SecondsLow");
        }
    }
}
